package ${servicePackage}.impl;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import jakarta.annotation.Resource;

import jp.co.binal.toss.framework.mvc.ServiceImpl;
import jp.co.binal.framework.mybatis.pagination.Page;
import jp.co.binal.framework.utils.ExceptionUtil;

import ${modelPackage}.${clazz.className};
import ${viewPackage}.${clazz.className}${viewSuffix};
import ${mapperPackage}.${clazz.className}ExMapper;
import ${servicePackage}.I${clazz.className}Service;

import static jp.co.binal.toss.domain.repository.${clazz.className}DynamicSqlSupport.${clazz.supportName};
import static jp.co.binal.toss.domain.repository.${clazz.className}DynamicSqlSupport.code;
import static jp.co.binal.toss.domain.repository.${clazz.className}Mapper.selectList;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;

/**
 * Comment:  ${clazz.classComment} service impl
 * @author: ${author}
 * @date:   ${date}
 */
@Service
public class ${clazz.className}ServiceImpl extends ServiceImpl implements I${clazz.className}Service {

    /**
     * log
     */
    private static final Logger logger = LoggerFactory.getLogger(${clazz.className}ServiceImpl.class);

    /**
     * mapper
     */
    @Resource
    private ${clazz.className}ExMapper mapper;

    @Override
    public List<${clazz.className}${viewSuffix}> queryAll() {
        SelectStatementProvider provider = SqlBuilder
                .select(selectList)
                .from(${clazz.supportName})
                .build().render(RenderingStrategies.MYBATIS3);
        return mapper.selectMany(provider)
                .stream()
                .map(item -> ${clazz.className}${viewSuffix}.model2View(item))
                .collect(Collectors.toList());
    }

    @Override
    public ${clazz.className}${viewSuffix} queryById(String id) {
        SelectStatementProvider provider = SqlBuilder
                .select(selectList)
                .from(${clazz.supportName})
                .where(code, isEqualTo(String.valueOf(id)))
                .build().render(RenderingStrategies.MYBATIS3);
        ${clazz.className}${viewSuffix} vo = null;
        Optional<${clazz.className}> optional = mapper.selectOne(provider);
        if (optional.isPresent()) {
            vo = ${clazz.className}${viewSuffix}.model2View(optional.get());
        }
        return vo;
    }

    @Override
    public List<${clazz.className}${viewSuffix}> queryPage(int pageNum, int pageSize) {
        Page page = new Page(pageNum, pageSize);
        SelectStatementProvider provider = SqlBuilder
                .select(selectList)
                .from(${clazz.supportName})
                .build().render(RenderingStrategies.MYBATIS3);
        return mapper.selectPage(page, provider)
                .stream()
                .map(item -> ${clazz.className}${viewSuffix}.model2View(item))
                .collect(Collectors.toList());
    }

    @Override
    public void save(${clazz.className}${viewSuffix} vo) {
        mapper.insertSelective(${clazz.className}${viewSuffix}.view2Model(vo));
    }

    @Override
    public void updateById(${clazz.className}${viewSuffix} vo) {
        if (mapper.updateByPrimaryKeySelective(${clazz.className}${viewSuffix}.view2Model(vo)) <= 0) {
            throw ExceptionUtil.buildTossException(logger, "update fail.");
        }
    }

    @Override
    public void saveOrUpdate(${clazz.className}${viewSuffix} vo) {
        Assert.notNull(vo, "view must not be null.");
        Optional<${clazz.className}> optional = mapper.selectByPrimaryKey(vo.${getPkMethod}());
        if (optional.isPresent()) {
            // update
            if (mapper.updateByPrimaryKeySelective(${clazz.className}${viewSuffix}.view2Model(vo)) <= 0) {
                throw ExceptionUtil.buildTossException(logger, "update fail.");
            }
        } else {
            // insert
            if (mapper.insertSelective(${clazz.className}${viewSuffix}.view2Model(vo)) <= 0) {
                throw ExceptionUtil.buildTossException(logger, "insert fail.");
            }
        }
    }

    @Override
    public void deleteById(String id) {
        if (mapper.deleteByPrimaryKey(id) <= 0) {
            throw ExceptionUtil.buildTossException(logger, "delete fail.");
        }
    }

}